home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / ip / ppp / mac / macppp2.0.1-src.hqx / MacPPP 2.0.1 src / fsm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-15  |  15.7 KB  |  667 lines

  1. /*
  2.  * fsm.c -- PPP Finite State Machine
  3.  *
  4.  * Copyright 1991-1992 William Allen Simpson
  5.  *  Licensed for non-profit non-commercial distribution
  6.  *  in Merit's PPP LAP for MacTCP
  7.  *
  8.  * Copyright 1992-1993 Merit Network, Inc. and The Regents of the
  9.  *  University of Michigan.  Usage of this source code is restricted
  10.  *  to non-profit, non-commercial purposes.  The source is provided
  11.  *  "as-is", without warranty.
  12.  *
  13.  * This code has been derived solely from the Jan 1991 public
  14.  *  domain release of PPP included in Phil Karn's KA9Q.
  15.  */
  16.  
  17. #include "ppp.h"
  18.  
  19. /* Convert header in host form to network form */
  20. void htoncnf(struct config_hdr *cnf, struct bufheader *bufptr)
  21. {
  22.     register b_8 *cp;
  23.  
  24.     /* Prepend bytes for LCP/IPCP header */
  25.     cp = (bufptr->dataptr -= CONFIG_HDR_LEN);
  26.     bufptr->length += CONFIG_HDR_LEN;
  27.  
  28.     /* Load header with proper values */
  29.     *cp++ = cnf->code;
  30.     *cp++ = cnf->id;
  31.     put16(cp, cnf->len);
  32. }
  33.  
  34. /* Extract header from incoming packet */
  35. short
  36. ntohcnf(struct config_hdr *cnf, struct bufheader *bufptr)
  37. {
  38.     b_8 cnfb[CONFIG_HDR_LEN];
  39.     register b_8 *ptr = cnfb;
  40.  
  41.     if ( yankbuf( bufptr, ptr, CONFIG_HDR_LEN ) < CONFIG_HDR_LEN )
  42.         return -1;
  43.  
  44.     cnf->code = *ptr++;
  45.     cnf->id = *ptr++;
  46.     cnf->len = get16(ptr);
  47.     return 0;
  48. }
  49.  
  50. /* Extract configuration option header */
  51. short
  52. ntohopt(struct option_hdr *opt, struct bufheader *bufptr)
  53. {
  54.     b_8 optb[OPTION_HDR_LEN];
  55.  
  56.     if ( yankbuf( bufptr, optb, OPTION_HDR_LEN ) < OPTION_HDR_LEN )
  57.         return -1;
  58.  
  59.     opt->type = optb[0];
  60.     opt->len = optb[1];
  61.     return 0;
  62. }
  63.  
  64. /* Set a timer in case an expected event does not occur */
  65. void
  66. fsm_timer(fsm_p)
  67. struct fsm_s *fsm_p;
  68. {
  69.     start_timer( &(fsm_p->timer) );
  70. }
  71.  
  72. /* Send a packet to the remote host */
  73. short
  74. fsm_send(struct fsm_s *fsm_p, b_8 code, b_8 id, struct bufheader *bufptr)
  75. {
  76.     LapInfo *lap = fsm_p->lap;
  77.     struct config_hdr hdr;
  78.     void *dummy = nil;        /* dummy ptr to indicate LCP echo req */
  79.  
  80.     if (bufptr == nil)
  81.         return -1;            /* Must pass a bufptr */
  82.  
  83.     switch( hdr.code = code ) {
  84.     case CONFIG_REQ:
  85.     case TERM_REQ:
  86.     case ECHO_REQ:
  87.         /* Save ID field for match against replies from remote host */
  88.         fsm_p->lastid = lap->ppp_id;
  89.         /* fallthru */
  90.     case PROT_REJ:
  91.     case DISCARD_REQ:
  92.         /* Use a unique ID field value */
  93.         hdr.id = lap->ppp_id++;
  94.         break;
  95.  
  96.     default:    /* CONFIG_ACK CONFIG_NAK CONFIG_REJ TERM_ACK CODE_REJ ECHO_REPLY */
  97.         /* Use ID sent by remote host */
  98.         hdr.id = id;
  99.         break;
  100.     }
  101.  
  102.     switch( code ) {
  103.     case ECHO_REQ:
  104.         dummy = bufptr;            /* special hack for LCP echo requests */
  105.         /* fall thru */
  106.     case DISCARD_REQ:
  107.         makeroom(bufptr, 4);    /* make space for magic number */
  108.         /* fall thru */
  109.     case ECHO_REPLY:            /* put our magic number here */
  110.         put32(bufptr->dataptr,
  111.             lap->lcp_i.local.work.lcp_option.magic_number);
  112.     };
  113.  
  114.     hdr.len = bufptr->length + CONFIG_HDR_LEN;
  115.  
  116.     /* Prepend header to packet data */
  117.     htoncnf(&hdr,bufptr);            /* prepend control protocol header */
  118.     htonppp(lap, fsm_p->pdc.protocol, bufptr);    /* prepend ppp header */
  119.     QueueFrame ( lap, bufptr, dummy );
  120.     return 0;
  121. }
  122.  
  123. /* Send a configuration request */
  124. short
  125. fsm_sendreq(fsm_p)
  126. struct fsm_s *fsm_p;
  127. {
  128.     struct bufheader *bufptr;
  129.  
  130.     if ( fsm_p->retry <= 0 )
  131.         return -1;
  132.  
  133.     fsm_p->retry--;
  134.     fsm_timer(fsm_p);
  135.  
  136.     bufptr = makereq(fsm_p);
  137.     return( fsm_send(fsm_p, CONFIG_REQ, 0, bufptr) );
  138. }
  139.  
  140. /* Send a termination request */
  141. static short
  142. fsm_sendtermreq(fsm_p)
  143. struct fsm_s *fsm_p;
  144. {
  145.     if ( fsm_p->retry <= 0 )
  146.         return -1;
  147.  
  148.     fsm_p->retry--;
  149.     fsm_timer(fsm_p);
  150.     return( fsm_send(fsm_p, TERM_REQ, 0, getbuffer()) );
  151. }
  152.  
  153. /* Send Terminate Ack */
  154. static short
  155. fsm_sendtermack(struct fsm_s *fsm_p, b_8 id)
  156. {
  157.     return( fsm_send(fsm_p, TERM_ACK, id, getbuffer()) );
  158. }
  159.  
  160. /* This layer is down */
  161. void
  162. fsm_tld(struct fsm_s *fsm_p)
  163. {
  164.     LapInfo *lap = fsm_p->lap;
  165.  
  166.     if (fsm_p->pdc.fsmi == Lcp) {
  167.         fsm_down( &(lap->ppp_fsm[IPcp]) );    /* IPCP down */
  168.         pap_down( &(lap->ppp_fsm[Pap]) );        /* PAP down */
  169.     }
  170. }
  171.  
  172. pascal void
  173. linkcloser( struct NMRec *nmrecord)
  174. {
  175.     link_close();
  176.     NMRemove(nmrecord);
  177. }
  178.  
  179. /* This layer is finished */
  180. void
  181. fsm_tlf(struct fsm_s *fsm_p)
  182. {
  183. register LapInfo    *lap = fsm_p->lap;
  184.  
  185.     stop_timer(&(fsm_p->timer));        /* stop the restart timer */
  186.     if (fsm_p->pdc.fsmi == Lcp) {
  187.         bzero((b_8 *) &lap->closenmtask, sizeof(struct NMRec));
  188.         lap->closenmtask.qType = nmType;
  189.         lap->closenmtask.nmResp = (NMProcPtr) linkcloser;
  190.         NMInstall(&lap->closenmtask);
  191.     } else    /* IPcp */
  192.         fsm_close( &(lap->ppp_fsm[Lcp]) );    /* close LCP */
  193. }
  194.  
  195. /* This layer up, Configuration negotiation complete */
  196. void
  197. fsm_tlu(struct fsm_s *fsm_p)
  198. {
  199.     LapInfo            *lap = fsm_p->lap;
  200.     struct proto_s    *proto_p = fsm_p->pdv;
  201.  
  202.     stop_timer(&(fsm_p->timer));
  203.     fsm_p->state = fsmOPENED;
  204.     
  205.     if (fsm_p->pdc.fsmi == Lcp) {
  206.         
  207.         /* Set Max Transmission Unit for outgoing packets */
  208.         lap->outMaxPacketSize = proto_p->remote.work.lcp_option.mru;
  209.         if ( (proto_p->remote.want_negotiate & LCP_N_MRU) &&
  210.             lap->outMaxPacketSize > proto_p->remote.want.lcp_option.mru)
  211.             lap->outMaxPacketSize = proto_p->remote.want.lcp_option.mru;
  212.  
  213.         /* set up async ctl maps */
  214.         lap->PPP_RecvACM = proto_p->local.work.lcp_option.accm;
  215.         lap->PPP_XmitACM = proto_p->remote.work.lcp_option.accm;
  216.  
  217.         /* check for authentication */
  218.         lap->ppp_phase = pppAUTHENTICATE;
  219.         lap->ppp_flags &= ~PPP_AP_REMOTE;
  220.     
  221.         if (proto_p->remote.work_negotiate & LCP_N_AUTHENT) {
  222.             if (proto_p->remote.work.lcp_option.authentication == PPP_PAP_PROTOCOL)
  223.                 pap_remote(lap);
  224.         }
  225.         /* re-check for authentication */
  226.         ppp_ready(lap);
  227.     } else {        /* IPcp */
  228.         int rslots = 0;
  229.         int tslots = 0;
  230.  
  231.         if (proto_p->local.work_negotiate & IPCP_N_COMPRESS)
  232.             rslots = proto_p->local.work.ipcp_option.slots;
  233.         if (proto_p->remote.work_negotiate & IPCP_N_COMPRESS) {
  234.             tslots = proto_p->remote.work.ipcp_option.slots;
  235.             if (tslots > IPCP_SLOT_HI)
  236.                 tslots = IPCP_SLOT_HI;
  237.         }
  238.         if ( rslots != 0 || tslots != 0 ) 
  239.             slhc_init( lap, rslots, tslots );
  240.     }
  241. }
  242.  
  243. /* This layer start */
  244. void
  245. fsm_tls(struct fsm_s *fsm_p)
  246. {
  247.     LapInfo *lap = fsm_p->lap;
  248.  
  249.     if (fsm_p->pdc.fsmi == Lcp) {
  250.         if (lap->ppp_phase == pppDEAD)
  251.             link_open(lap);        /* need to open link before we can start */
  252.         else
  253.             lap->ppp_phase = pppESTABLISH;    /* we are in establish phase */
  254.     } else /* IPcp */
  255.         fsm_open( &(lap->ppp_fsm[Lcp]) );    /* start LCP */
  256. }
  257.  
  258. /************************************************************************/
  259. /*            E V E N T   P R O C E S S I N G            */
  260. /************************************************************************/
  261.  
  262. /* Process incoming packet */
  263. void
  264. fsm_proc(struct fsm_s *fsm_p, struct bufheader *bufptr)
  265. {
  266.     struct config_hdr hdr;
  267.     short    result;
  268.     
  269.     switch(fsm_p->state) {
  270.         case fsmINITIAL:
  271.         case fsmSTARTING:
  272.             release(bufptr);
  273.             return;                /* not ready to receive packets yet */
  274.     }
  275.  
  276.     if ( ntohcnf(&hdr, bufptr) == -1 ) {
  277.         PPP_DEBUG_CHECKS("\pshort config packet" );
  278.         release(bufptr);
  279.         return;
  280.     }
  281.  
  282.     hdr.len -= CONFIG_HDR_LEN;        /* Length includes envelope */
  283.     
  284.     switch(hdr.code) {
  285.     case CONFIG_REQ:
  286.         switch(fsm_p->state) {
  287.         case fsmOPENED:        /* Unexpected event? */
  288.             fsm_tld(fsm_p);
  289.             fsm_sendreq(fsm_p);    /* send a new config request */
  290.             fsm_p->state =
  291.             (proc_request(fsm_p, &hdr, bufptr) == 0)
  292.                 ? fsmACK_Sent : fsmREQ_Sent;
  293.             break;
  294.         
  295.         case fsmSTOPPED:
  296.             fsm_reset(fsm_p);    /* init restart counter and reset option vars */
  297.             fsm_sendreq(fsm_p);
  298.             /* fallthru */
  299.         case fsmREQ_Sent:
  300.         case fsmACK_Sent:    /* Unexpected event? */
  301.             fsm_p->state =
  302.             (proc_request(fsm_p, &hdr, bufptr) == 0)
  303.                 ? fsmACK_Sent : fsmREQ_Sent;
  304.             break;
  305.  
  306.         case fsmACK_Rcvd:
  307.             if (proc_request(fsm_p, &hdr, bufptr) == 0) {
  308.                 fsm_tlu(fsm_p);
  309.             } else {
  310.                 /* give peer time to respond */
  311.                 fsm_timer(fsm_p);
  312.             }
  313.             break;
  314.  
  315.         case fsmCLOSED:
  316.             /* Don't accept any connections */
  317.             fsm_sendtermack(fsm_p, hdr.id);
  318.             /* We are attempting to close connection; */
  319.             /* wait for timeout to resend a Terminate Request */
  320.             /* fall thru */
  321.         default:    /* fsmCLOSING, fsmSTOPPING */
  322.             release(bufptr);
  323.         };
  324.         break;
  325.  
  326.     case CONFIG_ACK:
  327.         switch(fsm_p->state) {
  328.         case fsmREQ_Sent:
  329.         case fsmACK_Sent:
  330.             if (proc_ack(fsm_p, &hdr, bufptr) == 0) {
  331.                 fsm_p->retry = fsm_p->pdc.try_req;        /* initial restart counter */
  332.                 if (fsm_p->state == fsmREQ_Sent)
  333.                     fsm_p->state = fsmACK_Rcvd;
  334.                 else
  335.                     fsm_tlu(fsm_p);
  336.             }
  337.             break;
  338.  
  339.         case fsmOPENED:        /* Crossed connection? */
  340.             fsm_tld(fsm_p);
  341.             /* fallthru */
  342.         case fsmACK_Rcvd:    /* Crossed connection? */
  343.             release(bufptr);
  344.             fsm_sendreq(fsm_p);
  345.             fsm_p->state = fsmREQ_Sent;
  346.             break;
  347.  
  348.         case fsmCLOSED:
  349.         case fsmSTOPPED:
  350.             /* Out of Sync; kill the remote */
  351.             fsm_sendtermack(fsm_p, hdr.id);
  352.             /* fallthru */
  353.         default:    /* fsmCLOSING, fsmSTOPPING */
  354.             /* We are attempting to close connection; */
  355.             /* wait for timeout to resend a Terminate Request */
  356.             release(bufptr);
  357.         };
  358.         break;
  359.  
  360.     case CONFIG_NAK:
  361.     case CONFIG_REJ:
  362.         
  363.         switch(fsm_p->state) {
  364.         case fsmREQ_Sent:
  365.         case fsmACK_Sent:
  366.             fsm_p->retry = fsm_p->pdc.try_req;        /* initial restart counter */
  367.             /* Update our config request to reflect NAK/REJed options */
  368.             if (hdr.code == CONFIG_NAK)
  369.                 result = proc_nak(fsm_p, &hdr, bufptr);
  370.             else
  371.                 result = proc_reject(fsm_p, &hdr, bufptr);
  372.             if (result == 0)
  373.                 /* Send updated config request */
  374.                 fsm_sendreq(fsm_p);
  375.             break;
  376.  
  377.         case fsmOPENED:        /* Crossed connection? */
  378.             fsm_tld(fsm_p);
  379.             /* fallthru */
  380.         case fsmACK_Rcvd:    /* Crossed connection? */
  381.             release(bufptr);
  382.             fsm_sendreq(fsm_p);
  383.             fsm_p->state = fsmREQ_Sent;
  384.             break;
  385.  
  386.         case fsmCLOSED:
  387.         case fsmSTOPPED:
  388.             /* Out of Sync; kill the remote */
  389.             fsm_sendtermack(fsm_p, hdr.id);
  390.             /* fallthru */
  391.         default: /* fsmCLOSING, fsmSTOPPING */
  392.             /* We are attempting to close connection; */
  393.             /* wait for timeout to resend a Terminate Request */
  394.             release(bufptr);
  395.         };
  396.         break;
  397.  
  398.     case TERM_REQ:
  399.         release(bufptr);    /* release buffer */
  400.         switch(fsm_p->state) {
  401.         case fsmOPENED:
  402.             fsm_p->state=fsmSTOPPING;
  403.             fsm_tld(fsm_p);
  404.             fsm_sendtermack(fsm_p, hdr.id);
  405.             fsm_p->retry = 0;            /* zero restart counter */
  406.             fsm_timer(fsm_p);            /* restart the timer */
  407.             break;
  408.  
  409.         case fsmACK_Rcvd:
  410.         case fsmACK_Sent:
  411.             fsm_p->state = fsmREQ_Sent;
  412.             /* fallthru */
  413.         default:    /* REQ_Sent, CLOSED, STOPPED, CLOSING, STOPPING */
  414.             /* Unexpected, but make them happy */
  415.             fsm_sendtermack(fsm_p, hdr.id);
  416.         };
  417.         break;
  418.  
  419.     case TERM_ACK:
  420.         release(bufptr);    /* release buffer */
  421.         switch(fsm_p->state) {
  422.         case fsmCLOSING:
  423.             fsm_p->state = fsmCLOSED;
  424.             fsm_tlf(fsm_p);
  425.             break;
  426.         case fsmSTOPPING:
  427.             fsm_p->state = fsmSTOPPED;
  428.             fsm_tlf(fsm_p);
  429.             break;
  430.  
  431.         case fsmOPENED:
  432.             /* Remote host has abruptly closed connection */
  433.             fsm_tld(fsm_p);
  434.             fsm_sendreq(fsm_p);
  435.             fsm_p->state = fsmREQ_Sent;
  436.             break;
  437.  
  438.         case fsmACK_Rcvd:
  439.             fsm_p->state = fsmREQ_Sent;
  440.  
  441.         }
  442.         break;
  443.  
  444.     case CODE_REJ:
  445.     case PROT_REJ:        /* should add some code to see what was rejected */
  446.         release(bufptr);
  447.         if (fsm_p->state == fsmACK_Rcvd)
  448.                 fsm_p->state = fsmREQ_Sent;
  449.         break;
  450.  
  451.     case ECHO_REQ:
  452.         if (fsm_p->state == fsmOPENED)    /* should maybe check for looped request */
  453.             fsm_send( fsm_p, ECHO_REPLY, hdr.id, bufptr );
  454.         else
  455.             release(bufptr);    /* ignore */
  456.         break;
  457.  
  458.     case ECHO_REPLY:
  459.         fsm_p->lap->echo_count = 0;    /* reset echo counter */
  460.         /* fall thru */
  461.     case DISCARD_REQ:
  462.         release(bufptr);
  463.         break;
  464.  
  465.     default:
  466.         PPP_DEBUG_CHECKS("\pUnrecognized option type");
  467.         hdr.len += CONFIG_HDR_LEN;    /* restore length */
  468.         htoncnf( &hdr, bufptr );    /* put header back on */
  469.         fsm_send( fsm_p, CODE_REJ, hdr.id, bufptr );
  470.  
  471.         if (fsm_p->state == fsmOPENED) {
  472.             fsm_tld(fsm_p);
  473.             fsm_sendreq(fsm_p);
  474.             fsm_p->state = fsmREQ_Sent;
  475.         }
  476.     }
  477. }
  478.  
  479. /* Timeout while waiting for reply from remote host */
  480. static void
  481. fsm_timeout(void)
  482. {
  483.     struct TMtimer    *timerp;
  484.     struct fsm_s    *fsm_p;
  485.     
  486.     asm {
  487.             move.l    a1,timerp
  488.     }
  489.     fsm_p = timerp->fsm_p;
  490.  
  491.     switch(fsm_p->state) {
  492.     case fsmREQ_Sent:
  493.     case fsmACK_Rcvd:
  494.     case fsmACK_Sent:
  495.         if (fsm_p->retry > 0) {
  496.             fsm_sendreq(fsm_p);
  497.             fsm_p->state = (fsm_p->state == fsmACK_Sent ? fsmACK_Sent : fsmREQ_Sent);
  498.         } else {
  499.             fsm_p->state = fsmSTOPPED;
  500.             fsm_tlf(fsm_p);
  501.         }
  502.         break;
  503.  
  504.     case fsmCLOSING:
  505.     case fsmSTOPPING:
  506.         if (fsm_p->retry > 0) {
  507.             fsm_sendtermreq(fsm_p);
  508.         } else {
  509.             fsm_p->state = (fsm_p->state == fsmCLOSING ? fsmCLOSED : fsmSTOPPED);
  510.             fsm_tlf(fsm_p);
  511.         }
  512.         break;
  513.     }
  514. }
  515.  
  516. /************************************************************************/
  517. /*            A d m i n i s t r a t i v e    E v e n t s                    */
  518. /************************************************************************/
  519.  
  520. /* Up Event */
  521. void
  522. fsm_up(fsm_p)
  523. struct fsm_s *fsm_p;
  524. {
  525.     switch ( fsm_p->state ) {
  526.     case fsmSTARTING:
  527.         fsm_reset(fsm_p);        /* reset option values and the restart counter */
  528.         fsm_sendreq(fsm_p);
  529.         fsm_p->state = fsmREQ_Sent;
  530.         break;
  531.     case fsmINITIAL:
  532.         fsm_p->state = fsmCLOSED;
  533.     };
  534. }
  535.  
  536. /* Down Event */
  537. void
  538. fsm_down(fsm_p)
  539. struct fsm_s *fsm_p;
  540. {
  541.     switch ( fsm_p->state ) {
  542.     case fsmREQ_Sent:
  543.     case fsmACK_Rcvd:
  544.     case fsmACK_Sent:
  545.     case fsmSTOPPING:
  546.         stop_timer(&(fsm_p->timer));
  547.         fsm_p->state = fsmSTARTING;
  548.         break;
  549.  
  550.     case fsmOPENED:
  551.         fsm_p->state = fsmSTARTING;
  552.         fsm_tld(fsm_p);
  553.         break;
  554.     
  555.     case fsmSTOPPED:
  556.         fsm_p->state = fsmSTARTING;
  557.         /*    fsm_tls(fsm_p); */    /* don't restart link after term req. */
  558.         break;
  559.         
  560.     case fsmCLOSING:
  561.         stop_timer(&(fsm_p->timer));
  562.     case fsmCLOSED:
  563.         fsm_p->state = fsmINITIAL;
  564.     }
  565. }
  566.  
  567. /* Open Event */
  568. void
  569. fsm_open(fsm_p)
  570. struct fsm_s *fsm_p;
  571. {
  572.     switch ( fsm_p->state ) {
  573.     case fsmINITIAL:
  574.         fsm_p->state = fsmSTARTING;        /* we are starting */
  575.         fsm_tls(fsm_p);
  576.         break;
  577.     case fsmCLOSED:
  578.         fsm_reset(fsm_p);            /* reset options and init restart counter */
  579.         fsm_p->state = fsmREQ_Sent;
  580.         fsm_sendreq(fsm_p);
  581.         break;
  582.     case fsmCLOSING:
  583.         fsm_p->state = fsmSTOPPING;
  584.         /* fallthru */
  585.     case fsmSTOPPED:
  586.     case fsmSTOPPING:
  587.         fsm_down(fsm_p);        /* Implement the restart option */
  588.         fsm_up(fsm_p);
  589.     };
  590. }
  591.  
  592. /* Close Event */
  593. void
  594. fsm_close(fsm_p)
  595. struct fsm_s *fsm_p;
  596. {
  597.     switch ( fsm_p->state ) {
  598.     case fsmOPENED:
  599.         fsm_tld(fsm_p);    
  600.         /* fallthru */
  601.     case fsmACK_Sent:
  602.     case fsmREQ_Sent:
  603.     case fsmACK_Rcvd:
  604.         fsm_p->retry = fsm_p->pdc.try_terminate;
  605.         fsm_sendtermreq(fsm_p);
  606.         /* fallthru */
  607.     case fsmSTOPPING:
  608.         fsm_p->state = fsmCLOSING;
  609.         break;
  610.  
  611.     case fsmSTOPPED:
  612.         fsm_p->state = fsmCLOSED;
  613.         break;
  614.     
  615.     case fsmSTARTING:
  616.         fsm_p->state = fsmINITIAL;
  617.         break;
  618.  
  619.     /* case fsmCLOSED:   nothing to do */
  620.     };
  621. }
  622.  
  623. /* Initialize the fsm for this protocol
  624.  * Called from protocol _init
  625.  */
  626. void
  627. fsm_init(struct fsm_s *fsm_p)
  628. {
  629.     fsm_p->state = fsmINITIAL;        /* initialize state */
  630. }
  631.  
  632. /* Reset the option variables, and retry counters */
  633. static void
  634. fsm_reset(struct fsm_s *fsm_p)
  635. {
  636.     LapInfo            *lap = fsm_p->lap;
  637.     struct proto_s    *proto_p = fsm_p->pdv;
  638.  
  639.     if (fsm_p->pdc.fsmi == Lcp) {
  640.         BlockMove(&(lap->configdata.lcpconf.local), &(proto_p->local),
  641.                     sizeof( struct lcp_will_want )); 
  642.         BlockMove(&(lap->configdata.lcpconf.remote), &(proto_p->remote),
  643.                     sizeof( struct lcp_will_want ));
  644.         BlockMove(lap->lcp_default_p, &(proto_p->remote.work.lcp_option),
  645.                     sizeof( struct lcp_value_s ));
  646.         lap->PPP_RecvACM = lap->PPP_XmitACM = LCP_ACCM_DEFAULT;
  647.         fsm_p->retry = lap->configdata.lcpconf.req_tries; /* reset retry counter (config reqs.) */
  648.         fsm_p->pdc.timeout = lap->configdata.lcpconf.timeout;
  649.     } else {    /* IPcp */
  650.         BlockMove(&(lap->configdata.ipcpconf.local), &(proto_p->local),
  651.                     sizeof( struct ipcp_will_want ));
  652.         BlockMove(&(lap->configdata.ipcpconf.remote), &(proto_p->remote),
  653.                     sizeof( struct ipcp_will_want ));
  654.         BlockMove(lap->ipcp_default_p, &(proto_p->remote.work.ipcp_option),
  655.                     sizeof( struct ipcp_value_s ));    
  656.         fsm_p->retry = lap->configdata.ipcpconf.req_tries; /* reset retry counter (config reqs.) */
  657.         fsm_p->pdc.timeout = lap->configdata.ipcpconf.timeout;
  658.     }
  659.     BlockMove(&(proto_p->local.want), &(proto_p->local.work),
  660.                 sizeof (union value_s ));
  661.     proto_p->local.work_negotiate = proto_p->local.want_negotiate;
  662.     proto_p->remote.work_negotiate = FALSE;
  663.     fsm_p->pdc.try_req = fsm_p->retry;
  664.     fsm_p->retry_nak = fsm_p->pdc.try_nak;    /* reset the try nak counter */
  665.     /* Initialize timer */
  666.     set_timer(&(fsm_p->timer), fsm_p, (void *) fsm_timeout);
  667. }